package com.lost.octopus.es.helper.entity.wrapper;

import com.lost.octopus.es.helper.entity.model.FieldConfig;
import com.lost.octopus.es.helper.util.AgeUtil;
import com.lost.octopus.es.helper.util.DateUtil;
import com.lost.octopus.es.helper.util.StringUtil;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 年龄检索（推荐生日字段为long类型），扩展了 {@link EsQueryRangeWrapper}
 * 年龄计算规则：如：当天为20210825，则0~1岁为20190826到20210825
 * 重写了取值、字段名(默认fieldName)、默认全等查询
 * <br/>
 * 注解：{@code @EsSearch(fieldName = "csrq", queryType = EsQueryRangeAgeWrapper.class), otherParam="date"}
 * <br/>
 * 示例：{@code new Integer[]{1, 5}}
 * <br/>
 * 效果：{@code {"bool":{"must":[{"range":{"csrq":{"from":"20151218","to":"20201217","include_lower":true,"include_upper":true}}}]}} }
 * @author zhangbh
 **/
@Component
public class EsQueryRangeAgeWrapper extends EsQueryRangeWrapper {

    /**
     * 年龄需要转换成日期
     * @param value 值，逗号隔开
     * @return 取值
     */
    @Override
    protected List<Object> getValues(Object value, String fieldName, FieldConfig field) {
        List<Object> values = super.getValues(value, fieldName, field);
        if (CollectionUtils.isEmpty(values)) {
            return new ArrayList<>();
        }
        Object[] result = new Object[2];
        Object start = values.get(0);
        if (!StringUtil.isBlank(start)) {
            LocalDate startDay = LocalDate.now().minusYears(getYear(start)).minusDays(1L);
            String maxBirthday = field.isDateType() ? DateUtil.toString(startDay) : DateUtil.toString8(startDay);
            result[1] = maxBirthday;
        }
        Object end = values.size() > 1 ? values.get(1) : null;
        if (!StringUtil.isBlank(end)) {
            LocalDate endDay = LocalDate.now().minusYears(getYear(end) + 1L);
            String minBirthday = field.isDateType() ? DateUtil.toString(endDay) : DateUtil.toString8(endDay);
            result[0] = minBirthday;
        }
        return Arrays.stream(result).collect(Collectors.toList());
    }


    /**
     * 获取年份
     * @param value 数字
     * @return 年份
     */
    private int getYear(Object value) {
        // 检查是否是字符串或者数字
        if (value instanceof Integer) {
            return (Integer) value;
        }
        if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (Exception e) {
                throw new IllegalArgumentException("年龄查询，字符串格式有误");
            }
        }
        throw new IllegalArgumentException("年龄查询，必须是数字或者数字字符串");
    }

}
